/*!
    \file    xpt2046.c
    \brief   drive of xpt2046

    \version 2024-02-28, V1.0.0
*/
#include "xpt2046_drv.h"
#include "gd32f4xx_spi.h"
#include "gd32f4xx.h"
#include "stdio.h"
#include "string.h"
#include "softspi.h"
#define LCD_CS_PIN             GPIO_PIN_7
#define LCD_CS_PORT            GPIOF

#define LCD_SCK_PIN						 GPIO_PIN_8
#define LCD_SCK_PORT					 GPIOF

#define LCD_MOSI_PIN					 GPIO_PIN_9
#define LCD_MOSI_PORT					 GPIOF

#define LCD_MISO_PIN					 GPIO_PIN_6
#define LCD_MISO_PORT					 GPIOD

#define X_CMD													0xD0
#define Y_CMD 												0x90 

#define USE_TOUCH_ADJUST			 0

extern uint16_t display_memory_front[];
volatile touchParam_t touchParam = {0};
void xptdelay(uint32_t time)
{
    __IO uint32_t timecount = time;
    while(0 != timecount--);
}

void SoftSpiGpioInit(void)
{
		gpio_mode_set(LCD_CS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_CS_PIN); //CS
    gpio_output_options_set(LCD_CS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_CS_PIN);
	
		gpio_mode_set(LCD_SCK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_SCK_PIN); //SCK
    gpio_output_options_set(LCD_SCK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_SCK_PIN);
	
		gpio_mode_set(LCD_MOSI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_MOSI_PIN); //MOSI
    gpio_output_options_set(LCD_MOSI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_MOSI_PIN);
	
		gpio_mode_set(LCD_MISO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, LCD_MISO_PIN); //MISO
		
		gpio_mode_set(GPIOD, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_7);			//TOUCH_IRQ
}
void SckSetValue(bool value)
{
		if(value)
		{
				gpio_bit_set(LCD_SCK_PORT, LCD_SCK_PIN);
		}else{
				gpio_bit_reset(LCD_SCK_PORT, LCD_SCK_PIN);
		}
}
void MosiSetValue(bool value)
{
		if(value)
		{
				gpio_bit_set(LCD_MOSI_PORT, LCD_MOSI_PIN);
		}else{
				gpio_bit_reset(LCD_MOSI_PORT, LCD_MOSI_PIN);
		}
}
bool MisoGetValue(void)
{
		return gpio_input_bit_get(LCD_MISO_PORT,LCD_MISO_PIN);
}
void NssSetValue(bool value)
{
		if(value)
		{
				gpio_bit_set(LCD_CS_PORT, LCD_CS_PIN);
		}else{
				gpio_bit_reset(LCD_CS_PORT, LCD_CS_PIN);
		}
}

void Xpt2046Init(void)
{
    rcu_periph_clock_enable(RCU_SPI4);
		
		gpio_mode_set(GPIOD, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_7);
}


uint16_t Xpt2046CommandWrite(uint8_t cmd)
{
		uint8_t temp = cmd;
		return (uint16_t)SwapData(&cmd,3)>>3;
}
extern uint32_t current_time;

void Xpt2046TouchAdjust(void)
{
		if(USE_TOUCH_ADJUST==1)
		{
				/*using irq check point*/
				static uint32_t last_time = 0;
				/*start adjust*/
				touchPoint_t currentTouchPoint = {0};
				touchPoint_t refPointList[4] = {0};
				
				refPointList[0].x = 39;
				refPointList[0].y = 39;
				
				refPointList[1].x = 439;
				refPointList[1].y = 39;
				
				refPointList[2].x = 39;
				refPointList[2].y = 269;
				
				refPointList[3].x = 439;
				refPointList[3].y = 269;
				
				touchPoint_t realPointList[4] = {0};
				
				for(uint8_t i = 0;i<4;i++)
				{
					memset((void*)&display_memory_front[39*480+39+((i%2==0?0:1)*400)+(i>1?0:1)*(480*240)],0xFFFF,sizeof(uint16_t)*4);
				}
				for(uint8_t i = 0;i<4;i++)
				{
						printf("please press %i pos\r\n",i+1);
						while(1)
						{
								if(gpio_input_bit_get(GPIOD,GPIO_PIN_7)==0 && (current_time-last_time>1000))
								{
										currentTouchPoint = get_data();
										printf("X_pos = 0x%x,Y_pos = 0x%x\r\n",currentTouchPoint.x,currentTouchPoint.y);
										realPointList[i].x = currentTouchPoint.x;
										realPointList[i].y = currentTouchPoint.y;
										last_time = current_time;
										break;
								}
						}
				}
				
				touchParam.kx = (float)(refPointList[3].x - refPointList[0].x)/(realPointList[3].x - realPointList[0].x);
				touchParam.dx = (float)((float)refPointList[3].x - touchParam.kx*realPointList[3].x);
				
				touchParam.ky = (float)(refPointList[3].y - refPointList[0].y)/(realPointList[3].y - realPointList[0].y);
				touchParam.dy = (float)((float)refPointList[3].y - touchParam.ky*realPointList[3].y);
		
				for(uint8_t i = 0;i<4;i++)
				{
						realPointList[i].x = touchParam.kx * realPointList[i].x + touchParam.dx;
						realPointList[i].y = touchParam.ky * realPointList[i].y + touchParam.dy;
					
						printf("%d,%d\r\n",realPointList[i].x,realPointList[i].y);
				}
				
				printf("kx = %f,ky = %f,dx = %f, dy = %f\r\n",touchParam.kx,touchParam.ky,touchParam.dx,touchParam.dy);
				
				printf("sizeof Param = %d\r\n",sizeof(touchParam));				
		}else{
				touchParam.kx = 0.127024f;
				touchParam.ky = 0.080929f;
				touchParam.dx = -29.212158f;
				touchParam.dy = -14.898651f;
		}
}

touchPoint_t get_data(void)
{
		
		touchPoint_t currentTouchPoint;
		
		currentTouchPoint.y = Xpt2046CommandWrite(X_CMD);//
		
		xptdelay(2400);//delay1ms
		
		currentTouchPoint.x = Xpt2046CommandWrite(Y_CMD);
		
		return currentTouchPoint;
}

touchPoint_t GetCurrentTouchPoint(void)
{
		touchPoint_t adjustTouchPoint;
		adjustTouchPoint = get_data();
		adjustTouchPoint.x = (uint32_t)(touchParam.kx * adjustTouchPoint.x + touchParam.dx);
		adjustTouchPoint.y = (uint32_t)(touchParam.ky * adjustTouchPoint.y + touchParam.dy);
		return adjustTouchPoint;
}